package com.hollowlatte.manage.controller;


import com.hollowlatte.common.exceptionhandler.CustomException;
import com.hollowlatte.common.utils.Result;
import com.hollowlatte.manage.entity.Score;
import com.hollowlatte.manage.entity.vo.ScoreVO;
import com.hollowlatte.manage.service.CourseService;
import com.hollowlatte.manage.service.ScoreService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author Hollow Latte
 * @since 2021-05-05
 */
@RequiresPermissions("student:score:*")
@Tag(name = "ScoreController", description = "成绩管理")
@CrossOrigin
@RestController
@RequestMapping("/score")
public class ScoreController {
    private final ScoreService scoreService;

    private final CourseService courseService;

    public ScoreController(ScoreService scoreService, CourseService courseService) {
        this.scoreService = scoreService;
        this.courseService = courseService;
    }


    @Operation(summary = "添加学生成绩")
    @PostMapping()
    public Result addScore(@RequestBody @Valid ScoreVO scoreVO) {
        Score score = new Score();
        BeanUtils.copyProperties(scoreVO, score);
        boolean affect = scoreService.saveCourseScore(score);

        if (affect) {
            return Result.ok();
        } else {
            return Result.error();
        }
    }


    @Operation(summary = "通过学生id和课程id删除学生成绩")
    @DeleteMapping()
    public Result deleteScore(@RequestParam Long studentId, @RequestParam Long courseId) {
        boolean affect = scoreService.removeCourseScore(studentId, courseId);

        if (affect) {
            return Result.ok();
        } else {
            return Result.error();
        }
    }


    @Operation(summary = "修改学生成绩", description = "当id非null时，则根据id修改；否则根据学生id和课程id修改")
    @PutMapping()
    public Result updateScore(@RequestBody @Valid ScoreVO scoreVO) {
        Long scoreId = scoreVO.getId();
        Long studentId = scoreVO.getStudentId();
        Long courseId = scoreVO.getCourseId();

        Score score = new Score();
        score.setScore(scoreVO.getScore());

        boolean affect = false;

        if (scoreId != null) {
            score.setId(scoreId);
            affect = scoreService.updateById(score);
        } else if (studentId != null && courseId != null) {
            score.setStudentId(studentId);
            score.setCourseId(courseId);
            affect = scoreService.updateScoreByStudentIdAndCourseId(score);
        }

        if (affect) {
            return Result.ok();
        } else {
            return Result.error();
        }
    }


    @RequiresPermissions("student:score:check")
    @Operation(summary = "查询学生指定学期成绩", description = "当学期为null时查询所有学期")
    @GetMapping()
    public Result findTermScoreByStudentId(@RequestParam Long studentId, @RequestParam(required = false) Integer term) {
        Subject subject = SecurityUtils.getSubject();
        if (subject.hasRole("student")) {
            Long loginStudentId = (Long) subject.getPrincipal();
            if (!loginStudentId.equals(studentId)) {
                throw new CustomException("A0400", "无权限查询其他学生成绩");
            }
        }
        if (term == null) {
            List<Score> scoreList = scoreService.listScore(studentId);
            List<ScoreVO> scoreVOList = fillScoreToScoreVO(scoreList);

            return Result.ok().data("items", scoreVOList);
        }

        List<Score> scoreList = scoreService.listScoreByTerm(studentId, term);
        List<ScoreVO> scoreVOList = fillScoreToScoreVO(scoreList);

        return Result.ok().data("items", scoreVOList);
    }


    private List<ScoreVO> fillScoreToScoreVO(List<Score> scoreList) {
        List<ScoreVO> scoreVOList = new ArrayList<>();

        for (Score score : scoreList) {
            ScoreVO scoreVO = new ScoreVO();
            BeanUtils.copyProperties(score, scoreVO);
            scoreVO.setCourseName(courseService.getById(score.getCourseId()).getCourseName());
            scoreVOList.add(scoreVO);
        }

        return scoreVOList;
    }
}

